import { Types } from 'mongoose';
import { UserDAO } from '../dao/UserDAO';
import { RoleDAO } from '../dao/RoleDAO';
import { PermissionDAO } from '../dao/PermissionDAO';
import { OrganizationPermissionDAO } from '../dao/OrganizationPermissionDAO';
import { UserRoleDAO } from '../dao/UserRoleDAO';
import { RolePermissionDAO } from '../dao/RolePermissionDAO';
import { IUser } from '../models/user';
import { IRole } from '../models/role';
import { IPermission } from '../models/permission';
import { IPermissionTemplate, PermissionTemplate } from '../models/permissionTemplate';
import { hashPassword } from '../utils/superAdmin';

/**
 * 用户权限分配数据接口
 */
export interface AssignUserPermissionsData {
  userId: Types.ObjectId;
  permissionIds: Types.ObjectId[];
  systemId?: Types.ObjectId;
  expiresAt?: Date;
}

/**
 * 系统管理员分配数据接口
 */
export interface AssignSystemAdminData {
  userId: Types.ObjectId;
  systemId: Types.ObjectId;
  adminLevel: 'system' | 'subsystem';
  permissions?: Types.ObjectId[];
}

/**
 * 组织权限批量分配数据接口
 */
export interface BatchAssignOrganizationPermissionsData {
  organizationId: Types.ObjectId;
  organizationType: 'team' | 'department' | 'group';
  permissionIds: Types.ObjectId[];
  systemId?: Types.ObjectId;
  expiresAt?: Date;
}

/**
 * 权限模板创建数据接口
 */
export interface CreatePermissionTemplateData {
  name: string;
  description?: string;
  type: 'role' | 'organization' | 'user';
  permissionIds: Types.ObjectId[];
  roleIds?: Types.ObjectId[];
}

/**
 * 权限模板应用数据接口
 */
export interface ApplyPermissionTemplateData {
  templateId: Types.ObjectId;
  targetId: Types.ObjectId;
  targetType: 'user' | 'organization' | 'role';
  organizationType?: 'team' | 'department' | 'group';
  systemId?: Types.ObjectId;
}

/**
 * 管理员创建数据接口
 */
export interface CreateAdminData {
  username: string;
  email: string;
  password: string;
  realName: string;
  phone?: string;
  adminLevel: 'system' | 'subsystem';
  systemId?: Types.ObjectId;
  permissions?: Types.ObjectId[];
}

/**
 * 服务结果接口
 */
export interface SuperAdminServiceResult<T = any> {
  success: boolean;
  data?: T;
  message: string;
  auditLog?: {
    action: string;
    targetId?: Types.ObjectId;
    targetType?: string;
    details?: any;
  };
}

/**
 * 超级管理员服务类
 * 提供超级管理员相关的业务逻辑处理
 */
export class SuperAdminService {
  constructor(
    private userDAO: UserDAO,
    private roleDAO: RoleDAO,
    private permissionDAO: PermissionDAO,
    private organizationPermissionDAO: OrganizationPermissionDAO,
    private userRoleDAO: UserRoleDAO,
    private rolePermissionDAO: RolePermissionDAO
  ) {}

  /**
   * 分配用户权限
   * @param superAdminId 超级管理员ID
   * @param assignData 权限分配数据
   * @returns 分配结果
   */
  async assignUserPermissions(
    superAdminId: Types.ObjectId,
    assignData: AssignUserPermissionsData
  ): Promise<SuperAdminServiceResult> {
    try {
      // 验证超级管理员权限
      const superAdmin = await this.userDAO.findById(superAdminId);
      if (!superAdmin || !superAdmin.isSuperAdmin) {
        throw new Error('无权限执行此操作，需要超级管理员权限');
      }

      // 验证目标用户存在
      const targetUser = await this.userDAO.findById(assignData.userId);
      if (!targetUser) {
        throw new Error('目标用户不存在');
      }

      // 验证权限存在
      const permissions = await Promise.all(
        assignData.permissionIds.map(id => this.permissionDAO.findById(id))
      );
      const invalidPermissions = permissions.filter(p => !p);
      if (invalidPermissions.length > 0) {
        throw new Error('部分权限不存在');
      }

      // 创建角色来承载权限（如果用户没有专用角色）
      let userRole = await this.roleDAO.findByCode(`user_${targetUser._id}`);
      if (!userRole) {
        userRole = await this.roleDAO.create({
          name: `用户专用角色_${targetUser.username}`,
          code: `user_${targetUser._id}`,
          description: `用户 ${targetUser.username} 的专用权限角色`,
          level: 1,
          systemId: assignData.systemId,
          status: 1
        });
      }

      // 分配权限到角色
      await this.rolePermissionDAO.batchAssign(
        userRole._id as any,
        assignData.permissionIds,
        superAdminId as any,
        assignData.systemId
      );

      // 分配角色到用户
      await this.userRoleDAO.batchAssign([
        {
          userId: assignData.userId,
          roleId: userRole._id as any,
          assignedBy: superAdminId as any,
          systemId: assignData.systemId,
          status: 1
        }
      ]);

      return {
        success: true,
        data: {
          userId: assignData.userId,
          roleId: userRole._id,
          permissionIds: assignData.permissionIds,
          assignedAt: new Date()
        },
        message: '用户权限分配成功',
        auditLog: {
          action: 'ASSIGN_USER_PERMISSIONS',
          targetId: assignData.userId,
          targetType: 'user',
          details: {
            permissionIds: assignData.permissionIds,
            systemId: assignData.systemId,
            expiresAt: assignData.expiresAt
          }
        }
      };
    } catch (error: any) {
      return {
        success: false,
        message: `用户权限分配失败: ${error.message}`
      };
    }
  }

  /**
   * 撤销用户权限
   * @param superAdminId 超级管理员ID
   * @param userId 用户ID
   * @param permissionIds 要撤销的权限ID列表
   * @param systemId 系统ID（可选）
   * @returns 撤销结果
   */
  async revokeUserPermissions(
    superAdminId: Types.ObjectId,
    userId: Types.ObjectId,
    permissionIds: Types.ObjectId[],
    systemId?: Types.ObjectId
  ): Promise<SuperAdminServiceResult> {
    try {
      // 验证超级管理员权限
      const superAdmin = await this.userDAO.findById(superAdminId);
      if (!superAdmin || !superAdmin.isSuperAdmin) {
        throw new Error('无权限执行此操作，需要超级管理员权限');
      }

      // 验证目标用户存在
      const targetUser = await this.userDAO.findById(userId);
      if (!targetUser) {
        throw new Error('目标用户不存在');
      }

      // 获取用户的专用角色
      const userRole = await this.roleDAO.findByCode(`user_${userId}`);
      if (!userRole) {
        throw new Error('用户没有专用权限角色');
      }

      // 从角色中移除权限
      const revokedCount = await this.rolePermissionDAO.batchRevoke(
        userRole._id as any,
        permissionIds,
        systemId
      );

      return {
        success: true,
        data: {
          userId,
          roleId: userRole._id,
          revokedPermissionIds: permissionIds,
          revokedCount,
          revokedAt: new Date()
        },
        message: `成功撤销 ${revokedCount} 个用户权限`,
        auditLog: {
          action: 'REVOKE_USER_PERMISSIONS',
          targetId: userId,
          targetType: 'user',
          details: {
            permissionIds,
            systemId,
            revokedCount
          }
        }
      };
    } catch (error: any) {
      return {
        success: false,
        message: `用户权限撤销失败: ${error.message}`
      };
    }
  }

  /**
   * 分配系统管理员
   * @param superAdminId 超级管理员ID
   * @param assignData 系统管理员分配数据
   * @returns 分配结果
   */
  async assignSystemAdmin(
    superAdminId: Types.ObjectId,
    assignData: AssignSystemAdminData
  ): Promise<SuperAdminServiceResult> {
    try {
      // 验证超级管理员权限
      const superAdmin = await this.userDAO.findById(superAdminId);
      if (!superAdmin || !superAdmin.isSuperAdmin) {
        throw new Error('无权限执行此操作，需要超级管理员权限');
      }

      // 验证目标用户存在
      const targetUser = await this.userDAO.findById(assignData.userId);
      if (!targetUser) {
        throw new Error('目标用户不存在');
      }

      // 更新用户管理员级别
      const updatedUser = await this.userDAO.update(assignData.userId, {
        adminLevel: assignData.adminLevel,
        isSuperAdmin: false // 确保不是超级管理员
      });

      if (!updatedUser) {
        throw new Error('更新用户管理员级别失败');
      }

      // 如果指定了权限，则分配权限
      if (assignData.permissions && assignData.permissions.length > 0) {
        await this.assignUserPermissions(superAdminId, {
          userId: assignData.userId,
          permissionIds: assignData.permissions,
          systemId: assignData.systemId
        });
      }

      return {
        success: true,
        data: {
          userId: assignData.userId,
          adminLevel: assignData.adminLevel,
          systemId: assignData.systemId,
          permissions: assignData.permissions,
          assignedAt: new Date()
        },
        message: '系统管理员分配成功',
        auditLog: {
          action: 'ASSIGN_SYSTEM_ADMIN',
          targetId: assignData.userId,
          targetType: 'user',
          details: {
            adminLevel: assignData.adminLevel,
            systemId: assignData.systemId,
            permissions: assignData.permissions
          }
        }
      };
    } catch (error: any) {
      return {
        success: false,
        message: `系统管理员分配失败: ${error.message}`
      };
    }
  }

  /**
   * 批量分配组织权限
   * @param superAdminId 超级管理员ID
   * @param assignData 组织权限分配数据
   * @returns 分配结果
   */
  async batchAssignOrganizationPermissions(
    superAdminId: Types.ObjectId,
    assignData: BatchAssignOrganizationPermissionsData
  ): Promise<SuperAdminServiceResult> {
    try {
      // 验证超级管理员权限
      const superAdmin = await this.userDAO.findById(superAdminId);
      if (!superAdmin || !superAdmin.isSuperAdmin) {
        throw new Error('无权限执行此操作，需要超级管理员权限');
      }

      // 验证权限存在
      const permissions = await Promise.all(
        assignData.permissionIds.map(id => this.permissionDAO.findById(id))
      );
      const invalidPermissions = permissions.filter(p => !p);
      if (invalidPermissions.length > 0) {
        throw new Error('部分权限不存在');
      }

      // 批量分配组织权限
      const result = await this.organizationPermissionDAO.batchAssign(
        assignData.organizationId,
        assignData.organizationType,
        assignData.permissionIds,
        superAdminId,
        assignData.systemId,
        {
          expiresAt: assignData.expiresAt,
          inherited: false,
          source: 'direct'
        }
      );

      return {
        success: true,
        data: {
          organizationId: assignData.organizationId,
          organizationType: assignData.organizationType,
          successCount: result.success.length,
          failedCount: result.failed.length,
          successPermissions: result.success,
          failedPermissions: result.failed,
          assignedAt: new Date()
        },
        message: `组织权限批量分配完成，成功 ${result.success.length} 个，失败 ${result.failed.length} 个`,
        auditLog: {
          action: 'BATCH_ASSIGN_ORGANIZATION_PERMISSIONS',
          targetId: assignData.organizationId,
          targetType: assignData.organizationType,
          details: {
            permissionIds: assignData.permissionIds,
            systemId: assignData.systemId,
            expiresAt: assignData.expiresAt,
            successCount: result.success.length,
            failedCount: result.failed.length
          }
        }
      };
    } catch (error: any) {
      return {
        success: false,
        message: `组织权限批量分配失败: ${error.message}`
      };
    }
  }

  /**
   * 创建权限模板
   * @param superAdminId 超级管理员ID
   * @param templateData 权限模板数据
   * @returns 创建结果
   */
  async createPermissionTemplate(
    superAdminId: Types.ObjectId,
    templateData: CreatePermissionTemplateData
  ): Promise<SuperAdminServiceResult<IPermissionTemplate>> {
    try {
      // 验证超级管理员权限
      const superAdmin = await this.userDAO.findById(superAdminId);
      if (!superAdmin || !superAdmin.isSuperAdmin) {
        throw new Error('无权限执行此操作，需要超级管理员权限');
      }

      // 验证模板名称唯一性
      const existingTemplate = await PermissionTemplate.findByName(templateData.name);
      if (existingTemplate) {
        throw new Error('权限模板名称已存在');
      }

      // 验证权限存在
      const permissions = await Promise.all(
        templateData.permissionIds.map(id => this.permissionDAO.findById(id))
      );
      const invalidPermissions = permissions.filter(p => !p);
      if (invalidPermissions.length > 0) {
        throw new Error('部分权限不存在');
      }

      // 如果是角色模板，验证角色存在
      if (templateData.type === 'role' && templateData.roleIds) {
        const roles = await Promise.all(
          templateData.roleIds.map(id => this.roleDAO.findById(id))
        );
        const invalidRoles = roles.filter(r => !r);
        if (invalidRoles.length > 0) {
          throw new Error('部分角色不存在');
        }
      }

      // 创建权限模板
      const template = new PermissionTemplate({
        ...templateData,
        createdBy: superAdminId as any,
        status: 'active'
      });

      const savedTemplate = await template.save();

      return {
        success: true,
        data: savedTemplate,
        message: '权限模板创建成功',
        auditLog: {
          action: 'CREATE_PERMISSION_TEMPLATE',
          targetId: savedTemplate._id as any,
          targetType: 'permission_template',
          details: {
            name: templateData.name,
            type: templateData.type,
            permissionIds: templateData.permissionIds,
            roleIds: templateData.roleIds
          }
        }
      };
    } catch (error: any) {
      return {
        success: false,
        message: `权限模板创建失败: ${error.message}`
      };
    }
  }

  /**
   * 应用权限模板
   * @param superAdminId 超级管理员ID
   * @param applyData 权限模板应用数据
   * @returns 应用结果
   */
  async applyPermissionTemplate(
    superAdminId: Types.ObjectId,
    applyData: ApplyPermissionTemplateData
  ): Promise<SuperAdminServiceResult> {
    try {
      // 验证超级管理员权限
      const superAdmin = await this.userDAO.findById(superAdminId);
      if (!superAdmin || !superAdmin.isSuperAdmin) {
        throw new Error('无权限执行此操作，需要超级管理员权限');
      }

      // 获取权限模板
      const template = await PermissionTemplate.findById(applyData.templateId);
      if (!template) {
        throw new Error('权限模板不存在');
      }

      if (template.status !== 'active') {
        throw new Error('权限模板未激活');
      }

      let result: any;

      // 根据目标类型应用模板
      switch (applyData.targetType) {
        case 'user':
          result = await this.assignUserPermissions(superAdminId, {
            userId: applyData.targetId,
            permissionIds: template.permissionIds,
            systemId: applyData.systemId
          });
          break;

        case 'organization':
          if (!applyData.organizationType) {
            throw new Error('组织类型不能为空');
          }
          result = await this.batchAssignOrganizationPermissions(superAdminId, {
            organizationId: applyData.targetId,
            organizationType: applyData.organizationType,
            permissionIds: template.permissionIds,
            systemId: applyData.systemId
          });
          break;

        case 'role':
          // 分配权限到角色
          const rolePermissionResult = await this.rolePermissionDAO.batchAssign(
            applyData.targetId,
            template.permissionIds,
            superAdminId,
            applyData.systemId
          );
          result = {
            success: true,
            data: rolePermissionResult,
            message: '角色权限模板应用成功'
          };
          break;

        default:
          throw new Error('不支持的目标类型');
      }

      return {
        success: result.success,
        data: {
          templateId: applyData.templateId,
          templateName: template.name,
          targetId: applyData.targetId,
          targetType: applyData.targetType,
          appliedPermissions: template.permissionIds,
          appliedAt: new Date(),
          ...result.data
        },
        message: `权限模板 "${template.name}" 应用成功`,
        auditLog: {
          action: 'APPLY_PERMISSION_TEMPLATE',
          targetId: applyData.targetId,
          targetType: applyData.targetType,
          details: {
            templateId: applyData.templateId,
            templateName: template.name,
            permissionIds: template.permissionIds,
            systemId: applyData.systemId,
            organizationType: applyData.organizationType
          }
        }
      };
    } catch (error: any) {
      return {
        success: false,
        message: `权限模板应用失败: ${error.message}`
      };
    }
  }

  /**
   * 创建管理员
   * @param superAdminId 超级管理员ID
   * @param adminData 管理员数据
   * @returns 创建结果
   */
  async createAdmin(
    superAdminId: Types.ObjectId,
    adminData: CreateAdminData
  ): Promise<SuperAdminServiceResult<IUser>> {
    try {
      // 验证超级管理员权限
      const superAdmin = await this.userDAO.findById(superAdminId);
      if (!superAdmin || !superAdmin.isSuperAdmin) {
        throw new Error('无权限执行此操作，需要超级管理员权限');
      }

      // 验证用户名和邮箱唯一性
      const existingUserByUsername = await this.userDAO.findByUsername(adminData.username);
      if (existingUserByUsername) {
        throw new Error('用户名已存在');
      }

      const existingUserByEmail = await this.userDAO.findByEmail(adminData.email);
      if (existingUserByEmail) {
        throw new Error('邮箱已存在');
      }

      // 创建管理员用户
      const admin = await this.userDAO.create({
        username: adminData.username,
        email: adminData.email,
        password: adminData.password, // 密码将由模型自动加密
        realName: adminData.realName,
        phone: adminData.phone,
        adminLevel: adminData.adminLevel,
        isSuperAdmin: false,
        status: 'active'
      });

      // 如果指定了权限，则分配权限
      if (adminData.permissions && adminData.permissions.length > 0) {
        await this.assignUserPermissions(superAdminId, {
          userId: admin._id as any,
          permissionIds: adminData.permissions,
          systemId: adminData.systemId as any
        });
      }

      return {
        success: true,
        data: admin,
        message: '管理员创建成功',
        auditLog: {
          action: 'CREATE_ADMIN',
          targetId: admin._id as any,
          targetType: 'user',
          details: {
            username: adminData.username,
            email: adminData.email,
            adminLevel: adminData.adminLevel,
            systemId: adminData.systemId,
            permissions: adminData.permissions
          }
        }
      };
    } catch (error: any) {
      return {
        success: false,
        message: `管理员创建失败: ${error.message}`
      };
    }
  }

  /**
   * 分配管理员权限
   * @param superAdminId 超级管理员ID
   * @param adminId 管理员ID
   * @param permissionIds 权限ID列表
   * @param systemId 系统ID（可选）
   * @returns 分配结果
   */
  async assignAdminPermissions(
    superAdminId: Types.ObjectId,
    adminId: Types.ObjectId,
    permissionIds: Types.ObjectId[],
    systemId?: Types.ObjectId
  ): Promise<SuperAdminServiceResult> {
    try {
      // 验证超级管理员权限
      const superAdmin = await this.userDAO.findById(superAdminId);
      if (!superAdmin || !superAdmin.isSuperAdmin) {
        throw new Error('无权限执行此操作，需要超级管理员权限');
      }

      // 验证目标管理员存在且是管理员
      const admin = await this.userDAO.findById(adminId);
      if (!admin) {
        throw new Error('目标管理员不存在');
      }

      if (!admin.adminLevel || admin.adminLevel === 'user') {
        throw new Error('目标用户不是管理员');
      }

      // 使用现有的用户权限分配方法
      const result = await this.assignUserPermissions(superAdminId, {
        userId: adminId,
        permissionIds,
        systemId
      });

      return {
        success: result.success,
        data: {
          adminId,
          adminLevel: admin.adminLevel,
          permissionIds,
          systemId,
          assignedAt: new Date(),
          ...result.data
        },
        message: '管理员权限分配成功',
        auditLog: {
          action: 'ASSIGN_ADMIN_PERMISSIONS',
          targetId: adminId,
          targetType: 'admin',
          details: {
            adminLevel: admin.adminLevel,
            permissionIds,
            systemId
          }
        }
      };
    } catch (error: any) {
      return {
        success: false,
        message: `管理员权限分配失败: ${error.message}`
      };
    }
  }
}

export default SuperAdminService;